package com.desuntech.utils
{
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.SharedObject;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	import mx.events.ModuleEvent;
	
	import spark.modules.ModuleLoader;

	public class LocalCache
	{
		private static var _lc:LocalCache;
		private static var _oldConfig:Object;
		private static var _newConfig:XML;
		private static var _onReady:Function;
		private static var _onError:Function;
		private static var _onProgress:Function;
		private static var _moduleName:String;
		private static var _moduleUrl:String;
		private static var _newNode:XML;
		private static var _forceReload:Boolean;
		
		public static function getInstance():LocalCache {
			if (_lc == null)
				_lc = new LocalCache();
			return _lc;
		}
		
		public function CacheReBuild(url:String = 'Cache_config.xml', forceReload:Boolean = false):void {
			_forceReload = forceReload;
			var versions:SharedObject = SharedObject.getLocal('versions');
			_oldConfig = versions.data.content;
			
			var req:URLRequest = new URLRequest(url);
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, newConfigLoaded);
			loader.load(req);
		}
		
		private function newConfigLoaded(e:Event):void {
			var data:XML = XML((e.target as URLLoader).data);
			_newConfig = data;
		}
		
		public function load(name:String, url:String, onReady:Function, onError:Function, onProgress:Function):void {
			_moduleName = name;
			_moduleUrl = url;
			_onReady = onReady;
			_onError = onError;
			_onProgress = onProgress;
			var o:XMLList = _newConfig.data.(attribute('name') == _moduleName);
			_newNode = o[0];
			var module:ByteArray = SharedObject.getLocal(name).data.content;
			if(!_forceReload && module) {
				trace('缓存中有'+name+'模块的旧版本');
				if(_oldConfig[name]['version'] == _newNode.@version) {
					trace('直接调用缓存中的模块');
					var ml:ModuleLoader = new ModuleLoader();
					ml.addEventListener(ModuleEvent.READY,onLoadReady);
					ml.addEventListener(ModuleEvent.ERROR,onLoadError);
					ml.loadModule(_moduleUrl, module);
				} else {
					trace('缓存中的模块已过期，重新获取');
					reload(url);
				}
			} else {
				trace('缓存中没有该模块的旧版本，开始获取');
				reload(url);
			}
		}
		
		private function reload(url:String):void {
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfLoadComplete);
			loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, _onProgress);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, swfLoadError);
			loader.load(new URLRequest(url));
		}
		
		private function swfLoadComplete(e:Event):void {
			 e.target.removeEventListener(Event.COMPLETE, swfLoadComplete);
			 e.target.removeEventListener(IOErrorEvent.IO_ERROR, swfLoadError);
			 
			 var data:ByteArray = e.target.bytes;
			 
			 var soModule:SharedObject = SharedObject.getLocal(_moduleName);
			 soModule.data.content = data;
			 soModule.flush();
			 
			 if(!_oldConfig) {
				 _oldConfig = new Object();
				 _oldConfig[_moduleName] = new Object();
			 } else {
				 if(!_oldConfig[_moduleName]) {
					 _oldConfig[_moduleName] = new Object();
				 }
			 }
			 var version:String = _newNode.@version;
			 _oldConfig[_moduleName]['version'] = version;
			 var versions:SharedObject = SharedObject.getLocal('versions');
			 versions.data.content = _oldConfig;
			 versions.flush();
			 trace('本地版本号更新完毕');
			 
			 trace('模块缓存完毕，开始装载');
			 
			 var ml:ModuleLoader = new ModuleLoader();
			 ml.addEventListener(ModuleEvent.READY,onLoadReady);
			 ml.addEventListener(ModuleEvent.ERROR,onLoadError);
			 ml.loadModule(_moduleUrl, data);
		}
		
		private function onLoadReady(e:ModuleEvent):void {
			e.target.removeEventListener(Event.COMPLETE, onLoadReady);
			e.target.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
			trace('装载完毕');
			
			_onReady(e.module.factory.create());
		}
		
		private function swfLoadError(e:IOErrorEvent):void {
			e.target.removeEventListener(Event.COMPLETE, swfLoadComplete);
			e.target.removeEventListener(IOErrorEvent.IO_ERROR, swfLoadError);
			_onError(e);
		}
		
		private function onLoadError(e:ModuleEvent):void {
			e.target.removeEventListener(Event.COMPLETE, onLoadReady);
			e.target.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
			_onError(e);
		}
	}
}